﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using BusinessLogic;
using BusinessObjects;
using System.Net.Mail;
using Common;

namespace Presentation {
  /// <summary>
  /// Child diary form
  /// </summary>
  public partial class ChildDiaryForm : Form {

    private DiaryBll bll = new DiaryBll( );
    private BindingList<ChildDiary> currentList = new BindingList<ChildDiary>( );
    private BindingList<ChildDiary> originalList = new BindingList<ChildDiary>( );
    private List<string> nameList = new List<string>( );

    #region - Constructor -

    /// <summary>
    /// Initializes a new instance of the <see cref="ChildDiaryForm"/> class.
    /// </summary>
    public ChildDiaryForm( ) {
      InitializeComponent( );
      plusDayButton.Enabled = false;
      stateLabel.Text = string.Empty;
      dayDateTimePicker.DataBindings.Add( new Binding( "Value", bindingSource, "Day", true, DataSourceUpdateMode.OnPropertyChanged ) );
      dayDateTimePicker.PropertyChanged += new PropertyChangedEventHandler( dayDateTimePicker_PropertyChanged );

    }

    #endregion

    #region - Events -

    private void ChildDiaryForm_Load( object sender, EventArgs e ) {
      foreach ( ChildDiary item in currentList ) {
        originalList.Add( item.Copy( ) );
      }
      if ( !string.IsNullOrEmpty( departureTimeMaskTextBox.Text ) && departureTimeMaskTextBox.Text.Trim( ) != ":" ) {
        mailButton.Enabled = true;
      } else {
        mailButton.Enabled = false;
      }
      dayDateTimePicker.Value = DateTime.Now;
      SetData( dayDateTimePicker.Value.Value );
    }

    void dayDateTimePicker_PropertyChanged( object sender, PropertyChangedEventArgs e ) {
      if ( dayDateTimePicker.Value.Value.Date > ( DateTime.Now.Date ) ) {
        plusDayButton.Enabled = false;
        dayDateTimePicker.Value = DateTime.Now;
      } else {
        plusDayButton.Enabled = true;
      }
    }

    private void minusDayButton_Click( object sender, EventArgs e ) {
      DateTime date = dayDateTimePicker.Value.Value.AddDays( -1 );
      dayDateTimePicker.Value = date;
      plusDayButton.Enabled = true;
      SetData( date );
    }

    private void plusDayButton_Click( object sender, EventArgs e ) {
      DateTime date = dayDateTimePicker.Value.Value.AddDays( +1 );

      SetData( date );
    }

    private void bindingNavigatorMoveFirstItem_Click( object sender, EventArgs e ) {
      Navigate( PresentationHelper.BindingNavigatorMoveType.First );
    }

    private void bindingNavigatorMovePreviousItem_Click( object sender, EventArgs e ) {
      Navigate( PresentationHelper.BindingNavigatorMoveType.Previous );
    }

    private void bindingNavigatorMoveNextItem_Click( object sender, EventArgs e ) {
      Navigate( PresentationHelper.BindingNavigatorMoveType.Next );
    }

    private void bindingNavigatorMoveLastItem_Click( object sender, EventArgs e ) {
      Navigate( PresentationHelper.BindingNavigatorMoveType.Last );
    }

    private void bindingSource_CurrentItemChanged( object sender, EventArgs e ) {
      ChildDiary current = ( ChildDiary ) bindingSource.Current;
      stateLabel.Image = imageStateList.Images[ Convert.ToInt32( current.ChildActiveState ) ];
    }

    private void undoButton_Click( object sender, EventArgs e ) {
      UndoChanges( );
    }

    private void timeMaskTextBox_KeyPress( object sender, KeyPressEventArgs e ) {
      if ( !char.IsNumber( e.KeyChar ) && e.KeyChar != ( char ) Keys.Back
        && e.KeyChar != ( char ) Keys.Enter && e.KeyChar != ( char ) Keys.Tab ) {
        e.Handled = true;
      }
    }

    private void timeMaskTextBox_MouseDown( object sender, MouseEventArgs e ) {
      ( ( MaskedTextBox ) sender ).Select( 0, 5 );
    }

    private void saveButton_Click( object sender, EventArgs e ) {
      try {
        if ( ValidateChildren( ) ) {
          bll.Save( ( ChildDiary ) bindingSource.Current );
        }
      } catch ( DCMSExceptions.BusinessException ex ) {
        MessageBox.Show( ex.Message, "Bewaarfout", MessageBoxButtons.OK, MessageBoxIcon.Error );
      }
    }

    private void ChildDiaryForm_FormClosing( object sender, FormClosingEventArgs e ) {
      if ( Save( ) == null ) {
        e.Cancel = true;
      } else if ( Save( ) == false ) {
        e.Cancel = false;
      }
    }

    private void deleteButton_Click( object sender, EventArgs e ) {
      ChildDiary current = ( ChildDiary ) bindingSource.Current;
      if ( current != null && current.Id > 0 ) {
        if ( MessageBox.Show( "Ben je zeker dat je deze opvolging wilt verwijderen?", "Verwijderen", MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == System.Windows.Forms.DialogResult.Yes ) {
          try {
            bll.Delete( current );
            bindingSource.RemoveCurrent( );
          } catch ( Exception ex ) {
            MessageBox.Show( ex.Message, "Verwijderen mislukt", MessageBoxButtons.OK, MessageBoxIcon.Error );
          }
        }
      }
    }

    private void departureTimeMaskTextBox_Leave( object sender, EventArgs e ) {
      if ( string.IsNullOrEmpty( departureTimeMaskTextBox.Text ) || departureTimeMaskTextBox.Text.Trim( ) == ":" ) {
        mailButton.Enabled = false;
      } else {
        mailButton.Enabled = true;
      }
    }

    private void mailButton_Click( object sender, EventArgs e ) {
      if ( MailHelper.InternetConnectionAvailable( ) ) {

        ChildDiary current = ( ChildDiary ) bindingSource.Current;
        if ( current != null && current.Id > 0 ) {
          Child child = new ChildrenBll( ).GetChild( current.ChildId );
          string mailTo = string.Empty;
          if ( child.Mother.MainAddress ) {
            mailTo = child.Mother.Email;
          } else {
            mailTo = child.Father.Email;
          }
          if ( !string.IsNullOrEmpty( mailTo ) ) {
            string body = BuildMailBody( child );

            MailHelper.SendMail( SettingsSingleton.Settings.SystemEmail, 
              mailTo, child.FirstName + " " + child.Name + " " + "opvolging",
              body, SettingsSingleton.Settings.SmtpServerName, SettingsSingleton.Settings.SmtpPort, 
              SettingsSingleton.Settings.SmtpUserName, SettingsSingleton.Settings.SmtpPassword );

            MessageBox.Show( "Mail verzonden." );
          }
        } else {
          MessageBox.Show( "Er moet eerst bewaard worden.", "Bewaren", MessageBoxButtons.OK, MessageBoxIcon.Information );
        }
      } else {
        MessageBox.Show( "Geen internetverbinding gevonden.", "Geen verbinding.", MessageBoxButtons.OK, MessageBoxIcon.Information );
      }
    }

    #endregion

    #region - Methods -

    private void SetData( DateTime date ) {
      currentList = bll.GetDiaryOnDate( date );
      bindingSource.DataSource = currentList;
      bindingNavigator.BindingSource = bindingSource;
      childNameComboBox.ComboBox.DataSource = bindingSource;
      childNameComboBox.ComboBox.DisplayMember = "FullName";

    }

    private void Navigate( PresentationHelper.BindingNavigatorMoveType navi ) {
      if ( Save( ) != null ) {
        PresentationHelper.MoveBinding( this.bindingSource, navi );
      }

    }

    private bool UndoChanges( ) {
      errorProvider.Clear( );
      ChildDiary current = ( ChildDiary ) bindingSource.Current;
      bool undone = false;

      if ( current.HasChanged ) {
        for ( int i = 0; i < originalList.Count; i++ ) {
          if ( current.ChildId.Equals( originalList[ i ].ChildId ) ) {
            current = originalList[ i ].Copy( );
            break;
          }
        }
        //copy to bound currentlist
        for ( int i = 0; i < currentList.Count; i++ ) {
          if ( ( ( ChildDiary ) bindingSource.Current ).ChildId.Equals( currentList[ i ].ChildId ) ) {
            currentList[ i ] = current.Copy( );
            break;
          }
        }
        undone = true;
      }
      return undone;
    }

    private bool? Save( ) {
      bool? saved = null;
      if ( bindingSource.Current != null && ( ( ChildDiary ) bindingSource.Current ).HasChanged ) {
        DialogResult result = MessageBox.Show( "Wijzigingen bewaren?", "Wijzigingen", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question );
        if ( result == DialogResult.Yes ) {
          try {
            if ( ValidateChildren( ) ) {
              bll.Save( ( ChildDiary ) bindingSource.Current );
              saved = true;
            } else {
              saved = null;
            }
          } catch ( DCMSExceptions.BusinessException ex ) {
            MessageBox.Show( "Fout bij bewaren.\n" + ex.Message, "Bewaarfout", MessageBoxButtons.OK, MessageBoxIcon.Error );
          }
        } else if ( result == DialogResult.No ) {
          UndoChanges( );
          saved = false;
        }
      } else {
        saved = false;
      }
      return saved;
    }

    private string BuildMailBody( Child child ) {

      List<string> eatTimes = new List<string>( );
      if ( !string.IsNullOrEmpty( eatTime1MaskTextBox.Text ) && eatTime1MaskTextBox.Text.Trim( ) != ":" ) {
        eatTimes.Add( eatTime1MaskTextBox.Text );
      }
      if ( !string.IsNullOrEmpty( eatTime2MaskedTextBox.Text ) && eatTime2MaskedTextBox.Text.Trim( ) != ":" ) {
        eatTimes.Add( eatTime2MaskedTextBox.Text );
      }
      if ( !string.IsNullOrEmpty( eatTime3MaskedTextBox.Text ) && eatTime3MaskedTextBox.Text.Trim( ) != ":" ) {
        eatTimes.Add( eatTime3MaskedTextBox.Text );
      }

      StringBuilder bodyBuilder = new StringBuilder( );
      bodyBuilder.AppendLine( "Dagopvolging voor " + child.FirstName + " " + child.Name );
      bodyBuilder.Append( "Eten: " );
      foreach ( string eatTime in eatTimes ) {
        bodyBuilder.Append( eatTime + ", " );
      }
      bodyBuilder.Remove( bodyBuilder.Length - 2, 2 );
      bodyBuilder.AppendLine( "\n" + eatCommentTextBox.Text );
      bodyBuilder.Append( "\n Slaap: " );
      if ( !string.IsNullOrEmpty( sleepTimeFromMaskedTextBox.Text ) && sleepTimeFromMaskedTextBox.Text.Trim( ) != ":" ) {
        bodyBuilder.Append( "Van " + sleepTimeFromMaskedTextBox.Text );
        if ( !string.IsNullOrEmpty( sleepTimeToMaskTextBox.Text ) && sleepTimeToMaskTextBox.Text.Trim( ) != ":" ) {
          bodyBuilder.Append( " tot " + sleepTimeToMaskTextBox.Text );
        }
      }
      bodyBuilder.AppendLine( "\n" + sleepCommentTextBox.Text );
      bodyBuilder.AppendLine( "\nPamper/Potje: " );
      bodyBuilder.AppendLine( toiletCommentTextBox.Text );
      bodyBuilder.AppendLine( "\nAlgemeen dagverloop: " );
      bodyBuilder.AppendLine( dayCommentTextBox.Text );
      bodyBuilder.AppendLine( "\nOpgelet: " );
      bodyBuilder.AppendLine( noteCommentTextBox.Text );

      return bodyBuilder.ToString( );
    }

    #endregion

    #region - Validation -

    private void dayDateTimePicker_Validating( object sender, CancelEventArgs e ) {
      errorProvider.SetError( dayDateTimePicker, "" );
      if ( !dayDateTimePicker.Value.HasValue ) {
        errorProvider.SetError( plusDayButton, "Datum verplicht." );
        e.Cancel = true;
      }
    }

    private void arrivalTimeMaskTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateTimeBox( arrivalTimeMaskTextBox, e );
    }

    private void departureTimeMaskTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateToTimeBox( arrivalTimeMaskTextBox, departureTimeMaskTextBox, e );
    }

    private void eatTime1MaskTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateTimeBox( eatTime1MaskTextBox, e );
    }

    private void eatTime2MaskedTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateTimeBox( eatTime2MaskedTextBox, e );
    }

    private void eatTime3MaskedTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateTimeBox( eatTime3MaskedTextBox, e );
    }

    private void sleepTimeFromMaskedTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateTimeBox( sleepTimeFromMaskedTextBox, e );
    }

    private void sleepTimeToMaskTextBox_Validating( object sender, CancelEventArgs e ) {
      ValidateToTimeBox( sleepTimeFromMaskedTextBox, sleepTimeToMaskTextBox, e );
    }

    private void ValidateTimeBox( Control timeBoxControl, CancelEventArgs e ) {
      errorProvider.SetError( timeBoxControl, "" );
      if ( !string.IsNullOrEmpty( timeBoxControl.Text ) && timeBoxControl.Text.Trim( ) != ":" ) {
        Regex regex = new Regex( "^([0-1][0-9]|[2][0-3]):([0-5][0-9])$" );
        if ( !regex.IsMatch( timeBoxControl.Text ) ) {
          errorProvider.SetError( timeBoxControl, "Ongeldige tijd." );
          e.Cancel = true;
        }
      }
    }

    private void ValidateToTimeBox( Control fromControl, Control toControl, CancelEventArgs e ) {
      errorProvider.SetError( fromControl, "" );

      ValidateTimeBox( toControl, e );

      if ( !( string.IsNullOrEmpty( fromControl.Text ) || fromControl.Text.Trim( ) == ":" )
         && !( string.IsNullOrEmpty( toControl.Text ) || toControl.Text.Trim( ) == ":" ) ) {
        Regex regex = new Regex( "^([0-1][0-9]|[2][0-3]):([0-5][0-9])$" );
        if ( regex.IsMatch( fromControl.Text ) && regex.IsMatch( toControl.Text ) ) {
          TimeSpan fromTime = TimeSpan.Parse( fromControl.Text );
          TimeSpan toTime = TimeSpan.Parse( toControl.Text );
          if ( toTime <= fromTime ) {
            errorProvider.SetError( toControl, "Tot tijd moet groter dan Start tijd zijn." );
            e.Cancel = true;
          }
        }
      }
    }

    #endregion


  }
}
